#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import logging
from gi.repository import GLib
from wrt_const import WrtConst
from biz_connection import WrtConnectionManager
from biz_connection import WrtConnectionManagerCallback


class WrtCoreUplinkManager(WrtConnectionManagerCallback):

    def __init__(self, param, lv1_selector, lv2_selector, lv99_selector):
        self._param = param

        self._connMan = WrtConnectionManager(WrtConst.CONNECTION_LEVEL_1,
                                             self._param.pluginHub, self._param.prefixPool,
                                             self._param.mntNs, self._param.netNs,
                                             self)

        self._selector = lv1_selector
        self._selector.set_slaves(self._connMan)

        self._selectorLv2 = lv2_selector

        self._selectorLv99 = lv99_selector

    def start(self):
        self._connMan.start()

    def stop(self):
        self._connMan.stop()

    def on_connection_available(self, plugin_id, connection_id):
        self._selector.on_connection_available(plugin_id, connection_id, self._connMan.get_connection_data(connection_id))

    def on_connection_unavailable(self, plugin_id, connection_id, reason):
        self._selector.on_connection_unavailable(plugin_id, connection_id, reason)

    def on_connection_activated(self, plugin_id, connection_id, connection_livedata):
        self._selector.on_connection_activated(plugin_id, connection_id, connection_livedata)

        # report to upper level
        self._selectorLv2.on_lv1_connection_activated(plugin_id, connection_id, connection_livedata)
        self._selectorLv99.on_lv1_connection_activated(plugin_id, connection_id, connection_livedata)

    def on_connection_deactivated(self, plugin_id, connection_id, reason):
        self._selector.on_connection_deactivated(plugin_id, connection_id, reason)

        # report to upper level
        self._selectorLv2.on_lv1_connection_deactivated(plugin_id, connection_id, reason)
        self._selectorLv99.on_lv1_connection_deactivated(plugin_id, connection_id, reason)


class DefaultSelector:

    def __init__(self):
        self._cm = None
        self._conn_pending_list = []
        self._idle_id = None

    def dispose(self):
        if self._idle_id is not None:
            GLib.source_remove(self._idle_id)
            self._idle_id = None
        if True:
            self._conn_pending_list = []
        if True:
            self._cm = None

    def set_slaves(self, connection_manager):
        assert self._cm is None
        self._cm = connection_manager

    def on_connection_available(self, plugin_id, connection_id, connection_data):
        self._conn_pending_list.append(connection_id)
        if self._idle_id is None:
            self._idle_id = GLib.idle_add(self._idle_callback)

    def on_connection_unavailable(self, connection_id, reason):
        try:
            self._conn_pending_list.remove(connection_id)
        except ValueError:
            return

        if len(self._conn_pending_list) == 0:
            assert self._idle_id is not None
            GLib.source_remove(self._idle_id)
            self._idle_id = None

    def on_connection_activated(self, connection_id, connection_livedata):
        pass

    def on_connection_deactivated(self, connection_id, reason):
        pass

    def _idle_callback(self):
        try:
            for connection_id in self._conn_pending_list:
                self._cm.enable_connection(connection_id)
        except BaseException:
            logging.error("Error occured in DefaultSelectorLv01 idle callback", exc_info=True)
        finally:
            self._idle_id = None
            return False


class WrtUplink:

    def __init__(self):
        self._pluginId = None
        self._data = None
        self._liveData = None

        self._routeTable = None
        self._nameServer = None

        self._depList = []          # 




    @property
    def plugin_id(self):
        return self._pluginId

    @property
    def data(self):
        return self._data

    @property
    def live_data(self):
        return self._liveData




